package com.ap.core.business.message.response.translators.impl;

import com.ap.core.business.message.domain.translators.BindingMetaData;
import com.ap.core.business.message.response.translators.ResponseMetaData;
import com.ap.core.business.message.response.translators.ResponseTranslator;
import com.ap.core.business.message.response.translators.listener.ResponseListener;
import com.ap.core.common.types.MessageStatus;
import com.ap.core.common.types.PaymentResponseStatusType;
import com.ap.core.cxf.jaxb.common.CurrencyCodeType;
import com.ap.core.cxf.jaxb.common.QkPayDeliveryAddressType;
import com.ap.core.cxf.jaxb.managertp.NotifyRecipientInfoType;
import com.ap.core.cxf.jaxb.paymentdetails.*;
import com.ap.core.cxf.jaxb.rtp.TransactionCheckOutType;
import com.ap.core.dao.FinancialInstitutionDao;
import com.ap.core.dao.QuickPayDeliveryAddressDao;
import com.ap.core.dao.ZappConsumerUserDao;
import com.ap.core.domain.OrderPayment;
import com.ap.core.domain.QuickPayDeliveryAddress;
import com.ap.core.domain.ZappConsumerUser;
import com.ap.core.message.managertp.info.EnquireRTPMessageInfo;
import com.ap.core.message.managertp.info.ResponseEnquireRTPMessageInfo;
import org.joda.time.LocalDateTime;

/**
 * User: Ranjit.Singh
 * implementation class for {@link com.ap.core.business.message.response.translators.ResponseTranslator} to populate elements of {@link ResponseEnquireRTPMessageInfo}  in response object
 */
public class ResponseEnquireRTPStatusTranslator implements ResponseTranslator<EnquireRTPMessageInfo, ResponseEnquireRTPMessageInfo> {

    private ZappConsumerUserDao zappConsumerUserDao;
    private FinancialInstitutionDao financialInstitutionDao;
    private QuickPayDeliveryAddressDao quickPayDeliveryAddressDao;

    /**
     * {@inheritDoc}
     */
    @Override
    public void populateResponse(EnquireRTPMessageInfo request, ResponseEnquireRTPMessageInfo response, BindingMetaData bindingMetaData, ResponseMetaData responseMetaData, ResponseListener responseListener) {

        final OrderPayment originalOrderPayment = bindingMetaData.getOriginalReadOnlyOrderPayment();

        final NotifyRecipientInfoType notifyRecipientInfoType = new NotifyRecipientInfoType();
        notifyRecipientInfoType.setDistributorId(request.getSenderInfo().getDistributorId());
        notifyRecipientInfoType.setMerchantId(request.getSenderInfo().getMerchantId());
        notifyRecipientInfoType.setRTPId(request.getTransactionStatusEnq().getRTPId());

        response.setNotifyRecipientInfo(notifyRecipientInfoType);

        final NotifyPaymentDetailsType notifyPaymentDetailsType = new NotifyPaymentDetailsType();
        notifyPaymentDetailsType.setApTransactionId(request.getTransactionStatusEnq().getApTransactionId());
        notifyPaymentDetailsType.setApTRId(request.getTransactionStatusEnq().getApTRId());
        TxnStatusType txnStatusType = null;
        TxnStatusDescType txnStatusDescType = null;
        final NotifyPaymentStatusType notifyPaymentStatusType = new NotifyPaymentStatusType();
        notifyPaymentStatusType.setCurrency(CurrencyCodeType.valueOf(originalOrderPayment.getCurrencyCode()));
        notifyPaymentStatusType.setTotalPaymentReqAmount(originalOrderPayment.getTotalPaymentRequestAmount().getValue());
        final LocalDateTime currentTime = new LocalDateTime();
        switch (originalOrderPayment.getStatusCode()) {
            case AWAITING_RETRIEVAL:
                if (currentTime.isAfter(originalOrderPayment.getRetrievalExpiryTimeStmp())) {
                    txnStatusType = TxnStatusType.DECLINED;
                    txnStatusDescType = TxnStatusDescType.TRANSACTIONERROR;
                } else {
                    txnStatusType = TxnStatusType.INPROGRESS;
                }
                break;
            case AWAITING_PAYMENT_CONFIRMATION:
                if (currentTime.isAfter(originalOrderPayment.getConfirmationExpiryTimeStmp())) {
                    txnStatusType = TxnStatusType.DECLINED;
                    txnStatusDescType = TxnStatusDescType.TRANSACTIONERROR;
                } else {
                    txnStatusType = TxnStatusType.INPROGRESS;
                }
                break;
            case AUTHORISED:
                if (originalOrderPayment.getConfirmationTimeStmp().isAfter(originalOrderPayment.getConfirmationExpiryTimeStmp())) {
                    txnStatusType = TxnStatusType.DECLINED;
                    txnStatusDescType = TxnStatusDescType.TRANSACTIONERROR;
                } else {
                    txnStatusType = TxnStatusType.AUTHORISED;
                }
                break;
            case DECLINED:
                if (originalOrderPayment.getConfirmationTimeStmp().isAfter(originalOrderPayment.getConfirmationExpiryTimeStmp())) {
                    txnStatusType = TxnStatusType.DECLINED;
                    txnStatusDescType = TxnStatusDescType.TRANSACTIONERROR;
                } else {
                    txnStatusType = TxnStatusType.DECLINED;
                    txnStatusDescType = PaymentResponseStatusType.getMessageType(TransactionStatusCode.fromValue(originalOrderPayment.getTransactionStatusCode()));
                }
                break;
            case LATE_RETRIEVAL:
                txnStatusType = TxnStatusType.DECLINED;
                txnStatusDescType = TxnStatusDescType.TRANSACTIONERROR;
                break;
        }

        notifyPaymentStatusType.setPymtDecTimestamp(originalOrderPayment.getConfirmationTimeStmp());
        notifyPaymentStatusType.setTxnStatus(txnStatusType);
        notifyPaymentStatusType.setTxnStatusDesc(txnStatusDescType);


        notifyPaymentDetailsType.setPaymentStatusInfo(notifyPaymentStatusType);

        notifyPaymentDetailsType.setFasterPaymentsRef(originalOrderPayment.getFasterPaymentRef());

        if (MessageStatus.AUTHORISED.equals(originalOrderPayment.getStatusCode()) && TransactionCheckOutType.QKPACHK.equals(originalOrderPayment.getTransactionCheckoutType()) && !com.ap.core.cxf.jaxb.common.DeliveryType.DIGDEL.equals(originalOrderPayment.getDeliveryType())) {
            final QuickPayDeliveryAddress quickPayDeliveryAddress = quickPayDeliveryAddressDao.getReadOnlyQuickPayDeliveryAddressByAPTransactionId(request.getTransactionStatusEnq().getApTransactionId());

            final QkPayDeliveryAddressType qkPayDeliveryAddressType = new QkPayDeliveryAddressType();
            qkPayDeliveryAddressType.setAddressLine1(quickPayDeliveryAddress.getAddressLine1());
            qkPayDeliveryAddressType.setAddressLine2(quickPayDeliveryAddress.getAddressLine2());
            qkPayDeliveryAddressType.setAddressLine3(quickPayDeliveryAddress.getAddressLine3());
            qkPayDeliveryAddressType.setAddressLine4(quickPayDeliveryAddress.getAddressLine4());
            qkPayDeliveryAddressType.setAddressLine5(quickPayDeliveryAddress.getAddressLine5());
            qkPayDeliveryAddressType.setAddressLine6(quickPayDeliveryAddress.getAddressLine6());
            qkPayDeliveryAddressType.setCountryCode(quickPayDeliveryAddress.getCountryCode());
            qkPayDeliveryAddressType.setPostCode(quickPayDeliveryAddress.getPostCode());

            notifyPaymentDetailsType.setQkPayDelAddress(qkPayDeliveryAddressType);
        }


        if (TransactionCheckOutType.QKPACHK.equals(originalOrderPayment.getTransactionCheckoutType()) && com.ap.core.cxf.jaxb.common.DeliveryType.DIGDEL.equals(originalOrderPayment.getDeliveryType())) {
            final String fiIdentification = financialInstitutionDao.findById(originalOrderPayment.getFIId()).getFiIdentification();
            final ZappConsumerUser zappConsumerUser = zappConsumerUserDao.getZappConsumerUserByFiIdentificationAndZappCustomerId(fiIdentification, originalOrderPayment.getZappConsumerId());
            notifyPaymentDetailsType.setQkPayDelEmail(zappConsumerUser.getZappEmailId());
        }

        response.setPaymtDetails(notifyPaymentDetailsType);

        responseListener.onMessageResponse(response);

    }

    public void setZappConsumerUserDao(ZappConsumerUserDao zappConsumerUserDao) {
        this.zappConsumerUserDao = zappConsumerUserDao;
    }

    public void setFinancialInstitutionDao(FinancialInstitutionDao financialInstitutionDao) {
        this.financialInstitutionDao = financialInstitutionDao;
    }

    public void setQuickPayDeliveryAddressDao(QuickPayDeliveryAddressDao quickPayDeliveryAddressDao) {
        this.quickPayDeliveryAddressDao = quickPayDeliveryAddressDao;
    }
}
